/**
 * @file ZipFormat.cpp
 * @brief ZIP格式插件实现
 * @details 实现了ZIP格式的压缩和解压缩功能
 */

#include "ZipFormat.h"
#include <File.h>
#include <Directory.h>
#include <Entry.h>
#include <Path.h>
#include <String.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/**
 * @brief 构造函数
 */
ZipFormat::ZipFormat()
{
    // 构造函数不需要特殊初始化
}

/**
 * @brief 析构函数
 */
ZipFormat::~ZipFormat()
{
    // 析构函数不需要特殊清理
}

/**
 * @brief 获取插件支持的格式名称
 * @return 格式名称
 */
BString ZipFormat::GetFormatName() const
{
    return BString("ZIP");
}

/**
 * @brief 获取插件支持的文件扩展名列表
 * @return 扩展名列表，以分号分隔
 */
BString ZipFormat::GetSupportedExtensions() const
{
    return BString(".zip");
}

/**
 * @brief 检查插件是否支持指定的文件
 * @param filePath 文件路径
 * @return 是否支持
 */
bool ZipFormat::CanHandle(const char *filePath) const
{
    if (filePath == NULL)
    {
        return false;
    }

    // 检查文件扩展名
    BString path(filePath);
    if (path.IFindLast(".zip") >= 0)
    {
        return _IsZipFile(filePath);
    }

    return false;
}

/**
 * @brief 压缩文件或目录
 * @param sourcePath 源文件或目录路径
 * @param targetPath 目标压缩文件路径
 * @return 操作是否成功
 */
bool ZipFormat::Compress(const char *sourcePath, const char *targetPath)
{
    if (sourcePath == NULL || targetPath == NULL)
    {
        printf("错误：源路径或目标路径为空\n");
        return false;
    }

    // 检查源路径是否存在
    BEntry sourceEntry(sourcePath);
    if (!sourceEntry.Exists())
    {
        printf("错误：源文件或目录不存在：%s\n", sourcePath);
        return false;
    }

    // 构建压缩命令
    BString command;

    // 检查是文件还是目录
    if (sourceEntry.IsDirectory())
    {
        // 压缩目录
        command.SetTo("cd \"");
        command.Append(sourcePath);
        command.Append("\" && zip -r \"");
        command.Append(targetPath);
        command.Append("\" .");
    }
    else
    {
        // 压缩单个文件
        BPath path(sourcePath);
        command.SetTo("cd \"");
        command.Append(path.Path());
        command.Append("\" && zip \"");
        command.Append(targetPath);
        command.Append("\" \"");
        command.Append(path.Leaf());
        command.Append("\"");
    }

    // 执行压缩命令
    return _ExecuteZipCommand(command.String());
}

/**
 * @brief 解压缩文件
 * @param sourcePath 源压缩文件路径
 * @param targetPath 目标解压目录
 * @return 操作是否成功
 */
bool ZipFormat::Extract(const char *sourcePath, const char *targetPath)
{
    if (sourcePath == NULL || targetPath == NULL)
    {
        printf("错误：源路径或目标路径为空\n");
        return false;
    }

    // 检查源文件是否存在
    BEntry sourceEntry(sourcePath);
    if (!sourceEntry.Exists() || sourceEntry.IsDirectory())
    {
        printf("错误：源压缩文件不存在或不是文件：%s\n", sourcePath);
        return false;
    }

    // 检查是否为ZIP文件
    if (!_IsZipFile(sourcePath))
    {
        printf("错误：文件不是有效的ZIP格式：%s\n", sourcePath);
        return false;
    }

    // 检查目标目录是否存在，如果不存在则创建
    BEntry targetEntry(targetPath);
    if (!targetEntry.Exists())
    {
        status_t result = create_directory(targetPath, 0755);
        if (result != B_OK)
        {
            printf("错误：无法创建目标目录：%s\n", targetPath);
            return false;
        }
    }
    else if (!targetEntry.IsDirectory())
    {
        printf("错误：目标路径不是目录：%s\n", targetPath);
        return false;
    }

    // 构建解压命令
    BString command;
    command.SetTo("unzip -o \"");
    command.Append(sourcePath);
    command.Append("\" -d \"");
    command.Append(targetPath);
    command.Append("\"");

    // 执行解压命令
    return _ExecuteZipCommand(command.String());
}

/**
 * @brief 列出压缩文件中的内容
 * @param archivePath 压缩文件路径
 * @return 内容列表字符串
 */
BString ZipFormat::ListContents(const char *archivePath)
{
    if (archivePath == NULL)
    {
        return BString("错误：压缩文件路径为空");
    }

    // 检查文件是否存在
    BEntry entry(archivePath);
    if (!entry.Exists() || entry.IsDirectory())
    {
        return BString("错误：压缩文件不存在或不是文件");
    }

    // 检查是否为ZIP文件
    if (!_IsZipFile(archivePath))
    {
        return BString("错误：文件不是有效的ZIP格式");
    }

    // 构建命令
    BString command;
    command.SetTo("unzip -l \"");
    command.Append(archivePath);
    command.Append("\"");

    // 执行命令并获取输出
    FILE *pipe = popen(command.String(), "r");
    if (pipe == NULL)
    {
        return BString("错误：无法执行命令");
    }

    // 读取命令输出
    char buffer[1024];
    BString result;

    while (fgets(buffer, sizeof(buffer), pipe) != NULL)
    {
        result.Append(buffer);
    }

    pclose(pipe);

    return result;
}

/**
 * @brief 检查文件是否为ZIP格式
 * @param filePath 文件路径
 * @return 是否为ZIP格式
 */
bool ZipFormat::_IsZipFile(const char *filePath) const
{
    if (filePath == NULL)
    {
        return false;
    }

    // 打开文件
    BFile file(filePath, B_READ_ONLY);
    if (file.InitCheck() != B_OK)
    {
        return false;
    }

    // 读取文件头部
    uint8 header[4];
    ssize_t bytesRead = file.Read(header, sizeof(header));

    // 检查是否成功读取足够的字节
    if (bytesRead != sizeof(header))
    {
        return false;
    }

    // 检查ZIP文件头部标识（PK\x03\x04）
    if (header[0] == 0x50 && header[1] == 0x4B &&
        header[2] == 0x03 && header[3] == 0x04)
    {
        return true;
    }

    return false;
}

/**
 * @brief 执行ZIP命令行工具
 * @param command 命令行字符串
 * @return 执行是否成功
 */
bool ZipFormat::_ExecuteZipCommand(const char *command) const
{
    if (command == NULL)
    {
        return false;
    }

    // 执行命令
    int result = system(command);

    // 检查命令执行结果
    if (result != 0)
    {
        printf("命令执行失败：%s\n", command);
        return false;
    }

    return true;
}